/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "quakedef.h"
#include "menu.shared.h"


int	bind_grab = 0;


class qmenu_keybind_t : public qmenu_option_t
{
public:
	qmenu_keybind_t (char *command, char *name)
	{
		Q_strncpy (this->Text, name, sizeof (this->Text) - 1);
		Q_strncpy (this->Command, command, sizeof (this->Command) - 1);
		this->Active = TRUE;
	}

	int Draw (int y)
	{
		int	keys[2];

		M_PrintJustified (124, y, this->Text);

		this->FindKeysForCommand (keys);

		if (keys[0] == -1)
		{
			M_Print (144, y, "???");
		}
		else
		{
			const char *name = Key_KeynumToString (keys[0]);
			int x = strlen (name) * 8;

			M_PrintWhite (144, y, name);

			if (keys[1] != -1)
			{
				M_Print (144 + x + 8, y, "or");
				M_PrintWhite (144 + x + 32, y, Key_KeynumToString (keys[1]));
			}
		}

		return y + 10;
	}

	void DrawHighlight (int y)
	{
		// highlight is drawn wider for to fit key names
		if (bind_grab)
			M_DrawCharacter (130, y, '=');
		else M_DrawHighlight (y, 400);
	}

	BOOL Key (int key)
	{
		int	keys[2];

		if (bind_grab)
		{
			// defining a key
			m_soundlevel = m_sound_navigate;

			if (key == K_ESCAPE)
				bind_grab = FALSE;
			else if (key != '`')
				Cbuf_InsertText (va ("bind \"%s\" \"%s\"\n", Key_KeynumToString (key), this->Command));

			bind_grab = FALSE;
			return TRUE;
		}

		switch (key)
		{
		case K_ENTER:		// go into bind mode
			this->FindKeysForCommand (keys);
			m_soundlevel = m_sound_alert;

			if (keys[1] != -1)
				this->UnbindCommand ();

			bind_grab = TRUE;
			return TRUE;

		case K_BACKSPACE:		// delete bindings
		case K_DEL:				// delete bindings
			m_soundlevel = m_sound_enter;
			this->UnbindCommand ();
			return TRUE;
		}

		// not handled
		return FALSE;
	}

protected:
	void FindKeysForCommand (int *twokeys)
	{
		twokeys[0] = twokeys[1] = -1;

		int l = strlen (this->Command);
		int count = 0;

		for (int j = 0; j < 256; j++)
		{
			char *b = keybindings[j];

			if (!b)
				continue;

			if (!strncmp (b, this->Command, l))
			{
				twokeys[count] = j;
				count++;

				if (count == 2)
					break;
			}
		}
	}

	void UnbindCommand (void)
	{
		int l = strlen (this->Command);

		for (int j = 0; j < 256; j++)
		{
			char *b = keybindings[j];

			if (!b)
				continue;

			if (!strncmp (b, this->Command, l))
				Key_SetBinding (j, "");
		}
	}

	char Command[64];
};


class qmenu_keys_t : public qmenu_t
{
public:
	qmenu_keys_t (void)
	{
		// add our options to the menu
		this->AddOption (new qmenu_banner_t ("gfx/ttl_cstm.lmp"));
		this->AddOption (new qmenu_divider_t ());

		this->AddOption (new qmenu_dynamictext_t (this->DynamicText));
		this->AddOption (new qmenu_divider_t ());

		this->AddOption (new qmenu_keybind_t ("+attack", "attack"));
		this->AddOption (new qmenu_keybind_t ("impulse 10", "next weapon"));
		this->AddOption (new qmenu_keybind_t ("impulse 12", "prev weapon"));
		this->AddOption (new qmenu_divider_t ());

		this->AddOption (new qmenu_keybind_t ("+forward", "move forward"));
		this->AddOption (new qmenu_keybind_t ("+back", "move back"));
		this->AddOption (new qmenu_keybind_t ("+left", "turn left"));
		this->AddOption (new qmenu_keybind_t ("+right", "turn right"));
		this->AddOption (new qmenu_divider_t ());

		this->AddOption (new qmenu_keybind_t ("+jump", "jump/swim up"));
		this->AddOption (new qmenu_keybind_t ("+speed", "run"));
		this->AddOption (new qmenu_keybind_t ("+moveleft", "step left"));
		this->AddOption (new qmenu_keybind_t ("+moveright", "step right"));

		this->Register (m_keys);
	}

	void EnterFunc (void)
	{
		this->EnterMenu ();
	}

protected:
	void CustomDraw (void)
	{
		if (bind_grab)
			Q_strncpy (this->DynamicText, "Press a key or button for this action", sizeof (this->DynamicText) - 1);
		else Q_strncpy (this->DynamicText, "Enter to change, backspace to clear", sizeof (this->DynamicText) - 1);
	}

private:
	char DynamicText[64];
} menu_keys;


